package com.yeyks.commonReference.service.other.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Maps;
import com.yeyks.common.constants.hotel.HotelSourceType;
import com.yeyks.common.exception.ServiceException;
import com.yeyks.common.param.finance.FinanceInvoiceQueryParam;
import com.yeyks.common.utils.RedisUtil;
import com.yeyks.commonReference.pojo.param.other.InvoiceInfo.CreateInvoiceParam;
import com.yeyks.commonReference.pojo.param.other.InvoiceInfo.PreInvoicingOrderListParam;
import com.yeyks.commonReference.pojo.param.other.InvoiceInfo.PreInvoicingRechargeListParam;
import com.yeyks.commonReference.pojo.vo.other.InvoiceInfo.PreInvoicingOrderListOrderVo;
import com.yeyks.commonReference.pojo.vo.other.InvoiceInfo.PreInvoicingOrderListVo;
import com.yeyks.commonReference.pojo.vo.other.InvoiceInfo.PreInvoicingRechargeListRechargeVo;
import com.yeyks.commonReference.pojo.vo.other.InvoiceInfo.PreInvoicingRechargeListVo;
import com.yeyks.commonReference.service.order.OrderHeadService;
import com.yeyks.commonReference.service.other.InvoiceInfoService;
import com.yeyks.consumer.dal.domain.RechargeRecord;
import com.yeyks.consumer.dal.domain.UserInfo;
import com.yeyks.consumer.service.RechargeRecordService;
import com.yeyks.consumer.service.UserInfoService;
import com.yeyks.order.dal.domain.OrderHead;
import com.yeyks.other.dal.dao.InvoiceInfoMapper;
import com.yeyks.other.dal.domain.InvoiceInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.regex.Pattern;


/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author yun
 * @since 2020-02-05
 */
@Service
public class InvoiceInfoServiceImpl extends ServiceImpl<InvoiceInfoMapper, InvoiceInfo> implements InvoiceInfoService {

    @Autowired
    private OrderHeadService orderHeadService;
    @Autowired
    private RechargeRecordService rechargeRecordService;
    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private RedisUtil redisUtil;

    //获取最早可以开发票的事件
    private Date getLastDate() {
        return DateUtil.offsetMonth(DateUtil.beginOfDay(new Date()), -3).toJdkDate();
    }

    //查询未开票的订单
    private List<OrderHead> getOrderList(Integer userId, List<String> orderNoList) {
        //最后可开票的时间
        Date lastDate = getLastDate();
        return orderHeadService.list(
                new QueryWrapper<OrderHead>()
                        .eq(OrderHead.USER_ID, userId)
                        .eq(OrderHead.SOURCE_TYPE, HotelSourceType.CN)
                        .in(OrderHead.VIP_FLAG, 0, 2)
                        .in(OrderHead.STATUS, 3, 9)
                        .gt(OrderHead.CHECK_OUT, lastDate)
                        .in(CollectionUtil.isNotEmpty(orderNoList), OrderHead.ORDER_NO, orderNoList)
                        .isNull(OrderHead.INVOICE_ID)
        );
    }

    //查询未开票的充值订单
    private List<RechargeRecord> getRechargeList(Integer userId, List<String> orderNoList) {
        //最后可开票的时间
        Date lastDate = getLastDate();
        return rechargeRecordService.list(
                new QueryWrapper<RechargeRecord>()
                        .eq(RechargeRecord.USER_ID, userId)
                        .eq(RechargeRecord.TYPE, 4)
                        .gt(RechargeRecord.CREATED_TIME, lastDate)
                        .eq(RechargeRecord.STATUS, 2)
                        .in(CollectionUtil.isNotEmpty(orderNoList), RechargeRecord.ORDER_NO, orderNoList)
                        .isNull(RechargeRecord.INVOICE_ID)
        );
    }

    @Override
    public PreInvoicingOrderListVo getPreInvoicingOrderList(PreInvoicingOrderListParam param) {
        //分页
        PageHelper.startPage(param.getPageNum(), param.getPageSize(), true, null, true);
        //查询未开票的订单
        List<OrderHead> list = getOrderList(param.getUserId(), null);
        //分页对象
        PageInfo<OrderHead> pageInfo = new PageInfo<>(list);
        //返回的列表
        ArrayList<PreInvoicingOrderListOrderVo> listOrderVos = new ArrayList<>();
        List<OrderHead> orderHeadList = pageInfo.getList();
        //封装返回数据
        if (CollectionUtil.isNotEmpty(orderHeadList)) {
            for (OrderHead orderHead : orderHeadList) {
                PreInvoicingOrderListOrderVo preInvoicingOrderListOrderVo = new PreInvoicingOrderListOrderVo();
                preInvoicingOrderListOrderVo.setOrderNo(orderHead.getOrderNo());
                preInvoicingOrderListOrderVo.setHotelName(orderHead.getSnapshotHotelName());
                preInvoicingOrderListOrderVo.setCheckIn(orderHead.getCheckIn());
                preInvoicingOrderListOrderVo.setCheckOut(orderHead.getCheckOut());
                preInvoicingOrderListOrderVo.setSnapshotTotalFee(orderHead.getSnapshotTotalFee());
                listOrderVos.add(preInvoicingOrderListOrderVo);
            }
        }
        return new PreInvoicingOrderListVo().setList(listOrderVos);
    }

    @Override
    public PreInvoicingRechargeListVo getPreInvoicingRechangeList(PreInvoicingRechargeListParam param) {
        //最后可开票的时间
        Date lastDate = getLastDate();
        //分页
        PageHelper.startPage(param.getPageNum(), param.getPageSize(), true, null, true);
        //查询未开票的充值订单
        List<RechargeRecord> list = getRechargeList(param.getUserId(), null);
        //分页对象
        PageInfo<RechargeRecord> pageInfo = new PageInfo<>(list);
        //返回的列表
        ArrayList<PreInvoicingRechargeListRechargeVo> listOrderVos = new ArrayList<>();
        List<RechargeRecord> rechargeRecordList = pageInfo.getList();
        //封装返回数据
        if (CollectionUtil.isNotEmpty(rechargeRecordList)) {
            for (RechargeRecord rechargeRecord : rechargeRecordList) {
                PreInvoicingRechargeListRechargeVo preInvoicingRechargeListRechargeVo = new PreInvoicingRechargeListRechargeVo();
                preInvoicingRechargeListRechargeVo.setOrderNo(rechargeRecord.getOrderNo());
                preInvoicingRechargeListRechargeVo.setPayAmount(rechargeRecord.getPayAmount());
                preInvoicingRechargeListRechargeVo.setCreatedTime(rechargeRecord.getCreatedTime());
                listOrderVos.add(preInvoicingRechargeListRechargeVo);
            }
        }
        return new PreInvoicingRechargeListVo().setList(listOrderVos);
    }

    Pattern r = Pattern.compile("^\\w{1,32}$");

    @Override
    public Boolean getCreateInvoice(CreateInvoiceParam param) {
        return redisUtil.runWithLock("redisLock:InvoiceInfoService:getCreateInvoice:" + param.getUserId(),() -> {
            //企业发票校验税号
            if (Objects.equals(param.getHeadType(), 1)) {
                String taxId = param.getTaxId();
                if (StrUtil.isBlank(taxId) || !r.matcher(param.getTaxId()).matches()) {
                    throw new ServiceException("税号信息有误");
                }
            }
            //用户信息
            UserInfo userInfo = userInfoService.getById(param.getUserId());
            if (Objects.isNull(userInfo)) {
                throw new ServiceException("用户信息错误");
            }
            //订单金额
            Integer price = 0;
            switch (param.getInvoiceType()) {
                case 1:
                    List<OrderHead> orderList = getOrderList(param.getUserId(), param.getOrderNoList());
                    if (CollectionUtil.isEmpty(param.getOrderNoList())
                            || CollectionUtil.isEmpty(orderList)
                            || !Objects.equals(orderList.size(), param.getOrderNoList().size())) {
                        throw new ServiceException("订单信息有误");
                    }
                    for (OrderHead orderHead : orderList) {
                        price += orderHead.getSnapshotTotalFee();
                    }
                    break;
                case 2:
                    List<RechargeRecord> rechargeList = getRechargeList(param.getUserId(), param.getOrderNoList());
                    if (CollectionUtil.isEmpty(param.getOrderNoList())
                            || CollectionUtil.isEmpty(rechargeList)
                            || !Objects.equals(rechargeList.size(), param.getOrderNoList().size())) {
                        throw new ServiceException("订单信息有误");
                    }
                    for (RechargeRecord rechargeRecord : rechargeList) {
                        price += rechargeRecord.getPayAmount();
                    }
                    break;
                default:
                    break;
            }
            //开票对象
            InvoiceInfo invoiceInfo = new InvoiceInfo();
            invoiceInfo.setCreateTime(new Date());
            invoiceInfo.setHeadType(param.getHeadType());
            invoiceInfo.setInvoiceHead(param.getInvoiceHead());
            invoiceInfo.setTaxId(param.getTaxId());
            invoiceInfo.setPrice(price);
            invoiceInfo.setEmail(param.getEmail());
            invoiceInfo.setInvoiceStatus(0);
            invoiceInfo.setUserId(userInfo.getId());
            invoiceInfo.setUserName(userInfo.getName());
            invoiceInfo.setInvoiceType(param.getInvoiceType());
            boolean save = save(invoiceInfo);
            if (!save) {
                throw new ServiceException("订单信息有误");
            }
            //修改订单信息
            switch (param.getInvoiceType()) {
                case 1:
                    boolean updateO = orderHeadService.update(
                            new UpdateWrapper<OrderHead>()
                                    .set(OrderHead.INVOICE_ID, invoiceInfo.getId())
                                    .in(OrderHead.ORDER_NO, param.getOrderNoList())
                    );
                    if (!updateO) {
                        throw new ServiceException("订单信息有误");
                    }
                    break;
                case 2:
                    boolean updateR = rechargeRecordService.update(
                            new UpdateWrapper<RechargeRecord>()
                                    .set(RechargeRecord.INVOICE_ID, invoiceInfo.getId())
                                    .in(RechargeRecord.ORDER_NO, param.getOrderNoList())
                    );
                    if (!updateR) {
                        throw new ServiceException("订单信息有误");
                    }
                    break;
                default:
                    break;
            }
            return true;
        });
    }

    /**
     * 分页查询订单开票列表
     *
     * @param param 输入参数
     * @return 返回分页信息
     */
    @Override
    public Map<String, Object> orderInvoiceQueryByParam(FinanceInvoiceQueryParam param) {
        Map<String, Object> map = Maps.newHashMap();
        if (param.getInvoiceType() == null) {
            param.setInvoiceType(1);
        }
        PageHelper.startPage(param.getPageNum(), param.getPageSize());
        List<InvoiceInfo> invoiceInfoList = this.baseMapper.queryByParam(param);
        PageInfo<InvoiceInfo> pageInfo = PageInfo.of(invoiceInfoList);
        map.put("pageInfo", pageInfo);
        //查询申请中的count
        map.put("count", this.baseMapper.selectCount(new QueryWrapper<InvoiceInfo>()
                .eq(InvoiceInfo.INVOICE_STATUS, 0)
                .eq(InvoiceInfo.INVOICE_TYPE, param.getInvoiceType())));
        return map;
    }

    /**
     * 分页查询优享VIP开票
     *
     * @param param 输入参数
     * @return
     */
    @Override
    public Map<String, Object> rechargeInvoiceList(FinanceInvoiceQueryParam param) {
        if (param.getInvoiceType() == null) {
            //优享VIP
            param.setInvoiceType(2);
        }
        return orderInvoiceQueryByParam(param);
    }

}
